1   /*
2    * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package java.lang;
27  
28  import java.io.DataInputStream;
29  import java.io.InputStream;
30  import java.lang.ref.SoftReference;
31  import java.util.Arrays;
32  import java.util.zip.InflaterInputStream;
33  import java.security.AccessController;
34  import java.security.PrivilegedAction;
35  
36  class CharacterName {
37  
38      private static SoftReference<byte[]> refStrPool;
39      private static int[][] lookup;
40  
41      private static synchronized byte[] initNamePool() {
42          byte[] strPool = null;
43          if (refStrPool != null && (strPool = refStrPool.get()) != null)
44              return strPool;
45          DataInputStream dis = null;
46          try {
47              dis = new DataInputStream(new InflaterInputStream(
48                  AccessController.doPrivileged(new PrivilegedAction<InputStream>()
49                  {
50                      public InputStream run() {
51                          return getClass().getResourceAsStream("uniName.dat");
52                      }
53                  })));
54  
55              lookup = new int[(Character.MAX_CODE_POINT + 1) >> 8][];
56              int total = dis.readInt();
57              int cpEnd = dis.readInt();
58              byte ba[] = new byte[cpEnd];
59              dis.readFully(ba);
60  
61              int nameOff = 0;
62              int cpOff = 0;
63              int cp = 0;
64              do {
65                  int len = ba[cpOff++] & 0xff;
66                  if (len == 0) {
67                      len = ba[cpOff++] & 0xff;
68                      // always big-endian
69                      cp = ((ba[cpOff++] & 0xff) << 16) |
70                           ((ba[cpOff++] & 0xff) <<  8) |
71                           ((ba[cpOff++] & 0xff));
72                  }  else {
73                      cp++;
74                  }
75                  int hi = cp >> 8;
76                  if (lookup[hi] == null) {
77                      lookup[hi] = new int[0x100];
78                  }
79                  lookup[hi][cp&0xff] = (nameOff << 8) | len;
80                  nameOff += len;
81              } while (cpOff < cpEnd);
82              strPool = new byte[total - cpEnd];
83              dis.readFully(strPool);
84              refStrPool = new SoftReference<>(strPool);
85          } catch (Exception x) {
86              throw new InternalError(x.getMessage());
87          } finally {
88              try {
89                  if (dis != null)
90                      dis.close();
91              } catch (Exception xx) {}
92          }
93          return strPool;
94      }
95  
96      public static String get(int cp) {
97          byte[] strPool = null;
98          if (refStrPool == null || (strPool = refStrPool.get()) == null)
99              strPool = initNamePool();
100         int off = 0;
101         if (lookup[cp>>8] == null ||
102             (off = lookup[cp>>8][cp&0xff]) == 0)
103             return null;
104         return new String(strPool, 0, off >>> 8, off & 0xff);  // ASCII
105     }
106 }